package charlie.shop.warehouse;

import com.charlie.beans.Product;
import com.charlie.beans.ShipmentOrder;
import com.charlie.beans.SoHistory;
import com.charlie.beans.SoProduct;
import com.charlie.beans.Users;
import com.charlie.mail.MailLocal;
import com.charlie.mail.MailTemplate;
import com.charlie.mail.MailTemplateType;
import com.charlie.sessions.ProductFacadeLocal;
import com.charlie.sessions.ShipmentOrderFacadeLocal;
import com.charlie.sessions.SoHistoryFacadeLocal;
import com.charlie.sessions.SoProductFacadeLocal;
import com.charlie.sessions.StatusDictFacadeLocal;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Displays selected order contents and allow to edit it.
 *
 * @author Alexandra
 */
@WebServlet(name = "OrderItem", urlPatterns = {"/warehouse/order/*"})
public class OrderItem extends HttpServlet {

    /**
     * Representation statuses into number value
     */
    private static final Integer QUEUE_STATUS = 1;
    private static final Integer SHIPPING_STATUS = 2;
    private static final Integer CANCELED_STATUS = 4;
    private static final Integer DEFAULT_AMOUNT = 1;
    @EJB
    private ProductFacadeLocal prod;
    @EJB
    private SoProductFacadeLocal soProd;
    @EJB
    private ShipmentOrderFacadeLocal order;
    @EJB
    private StatusDictFacadeLocal statusEJB;
    @EJB
    private SoHistoryFacadeLocal historyItem;
    @EJB
    private MailLocal mail;
    /**
     * Current order to work with
     */
    public ShipmentOrder currentOrder;
    /**
     * Map holds product and it count in SO
     */
    public Map<Product, Integer> prList = new HashMap<Product, Integer>();
    /**
     * Collection holds list of products to add to current order
     */
    private Collection<SoProduct> toAdd = new ArrayList<SoProduct>();
    /**
     * Collection holds list of products to delete from current order
     */
    private Collection<SoProduct> toDelete = new ArrayList<SoProduct>();

    /**
     * Displays order content, process editing.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        if (request.getParameterValues("idOfOrder") != null) {
            prList.clear();
            toAdd.clear();
            toDelete.clear();

            try {
                currentOrder = order.find(Integer.valueOf(request.getParameter("idOfOrder")));
                for (SoProduct s : currentOrder.getSoProductCollection()) {
                    prList.put(s.getProductId(), s.getAmount());
                }
            } catch (Exception e) {
            }
            if (currentOrder.getSoHistoryCollection().size() == 0) {  //no records in history 

                getServletContext().setAttribute("order", currentOrder);
            }
            getServletContext().setAttribute("productsList", prList);
            getServletContext().getRequestDispatcher("/warehouse/orderItem.jsp").forward(request, response);

        } else {

            if (request.getParameter("id") != null) {
                try {
                    Product addedProduct = (Product) prod.find(Integer.valueOf(request.getParameter("id")));

                    if (prList.containsKey(addedProduct)) {
                        Integer count = prList.get(addedProduct);
                        prList.put(addedProduct, ++count);
                        currentOrder.setCost(currentOrder.getCost() + addedProduct.getCost());

                    } else {

                        SoProduct addProd = new SoProduct();
                        addProd.setProductId(addedProduct);
                        addProd.setSoId(currentOrder);
                        addProd.setAmount(DEFAULT_AMOUNT);

                        toAdd.add(addProd);
                        currentOrder.setCost(currentOrder.getCost() + addedProduct.getCost() * addProd.getAmount());
                        prList.put(addedProduct, addProd.getAmount());
                    }
                } catch (Exception e) {
                }
            }

            if (request.getParameter("idRemove") != null) {
                Map<Product, Integer> prListTemp = new HashMap<Product, Integer>();
                currentOrder.setCost(0);

                for (Product t : prList.keySet()) {
                    if (!t.getProductId().equals(Integer.valueOf(request.getParameter("idRemove")))) {
                        prListTemp.put(t, prList.get(t));
                        currentOrder.setCost(currentOrder.getCost() + t.getCost() * prList.get(t));
                    } else {
                        for (SoProduct s : currentOrder.getSoProductCollection()) {
                            if (s.getProductId().equals(t) && (s.getSoId().equals(currentOrder))) {

                                toDelete.add(s);
                            }
                        }
                    }
                }

                prList = prListTemp;
            }

            if (request.getParameter("productCount") != null) {
                if (request.getParameter("productToChange") != null) {
                    currentOrder.setCost(0);
                    for (Product pr : prList.keySet()) {

                        if (pr.getProductId().equals(Integer.valueOf(request.getParameter("productToChange")))) {

                            prList.put(pr, Integer.valueOf(request.getParameter("productCount")));
                        }
                        currentOrder.setCost(currentOrder.getCost() + pr.getCost() * prList.get(pr));
                    }
                    for (SoProduct so : toAdd) {
                        if (so.getProductId().getProductId().equals(Integer.valueOf(request.getParameter("productToChange")))) {
                            so.setAmount(Integer.valueOf(request.getParameter("productCount")));
                        }
                    }
                }

            }

            if (request.getParameter("apply") != null) {

                if (!prList.isEmpty()) {
                    addHistoryRecord(SHIPPING_STATUS, request);
                    updateOrder();
                } else {
                    request.setAttribute("item", 0);
                    getServletContext().getRequestDispatcher("/warehouse/orderItem.jsp").forward(request, response);
                    return;
                }
                response.sendRedirect(request.getContextPath() + "/warehouse/orders");
                MailTemplate tpl = new MailTemplate(MailTemplateType.WH_ACCEPT);
                mail.send(currentOrder.getEmail(), "CharlieShop: order accepted", tpl);
                return;
            }
            if (request.getParameter("cancel") != null) {
                addHistoryRecord(CANCELED_STATUS, request);
                response.sendRedirect(request.getContextPath() + "/warehouse/orders");
                if (currentOrder.getIsSubscribed() == 1) {
                    MailTemplate tpl = new MailTemplate(MailTemplateType.CANCEL);
                    mail.send(currentOrder.getEmail(), "CharlieShop: order canceled", tpl);
                }
                return;
            }

            getServletContext().setAttribute("productsList", prList);
            getServletContext().getRequestDispatcher("/warehouse/orderItem.jsp").forward(request, response);
        }
    }

    /**
     * Update shipment order
     */
    private void updateOrder() {
        try {
            soProd.addItems(toAdd);
            for (SoProduct so : toDelete) {
                soProd.remove(so);

            }
            Collection<SoProduct> finalList = new ArrayList<SoProduct>();
            for (Product p : prList.keySet()) {
                SoProduct so = soProd.updateAmountBYorderID_and_soID(p, currentOrder, prList.get(p));
                finalList.add(so);
            }
            currentOrder.setSoProductCollection(finalList);
            order.edit(currentOrder);

        } catch (Exception e) {
        }
    }

    /**
     * Add So status into History table
     *
     * @param status
     * @param request servlet request
     */
    private void addHistoryRecord(Integer status, HttpServletRequest request) {
        SoHistory record = new SoHistory();
        record.setChangeDate(new Date());
        record.setSoId(currentOrder);
        HttpSession session = (HttpSession) request.getSession(false);

        Users user = (Users) session.getAttribute("user");
        if (user != null) {
            record.setUserId(user);
        }
        if (request.getParameter("commentForOrder") != null) {
            record.setCommentary(request.getParameter("commentForOrder"));
        }
        try {
            record.setStatusDictId(statusEJB.find(status));
            historyItem.create(record);
        } catch (Exception e) {
        }

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}
